package com.demo.xj_plane.common.utils;

import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/*
 * 报文处理组件，用于提取各项气象要素
 * */
public class MessageUtils {
    public MessageUtils() {
    }

    /**
     * 报文数据转换
     * 转换前：
     * SAHK31 RCSS 220830
     * METAR RCSS 220830Z 32005KT 9999 -RA FEW020 BKN040 32/25 Q1009
     * NOSIG RMK A2981=
     * 转换后：
     * METAR RCSS 220830Z 32005KT 9999 -RA FEW020 BKN040 32/25 Q1009 NOSIG RMK A2981=
     *
     * @param reportMessage
     */
    public static String getReportBody(String reportMessage) {
        String reportType = getReportType(reportMessage);
        int startIndex = reportMessage.indexOf(reportType);
        int endIndex = reportMessage.indexOf("=");
        String reportBody = reportMessage.substring(startIndex, endIndex);
        String reportText = reportBody + "=";
        reportText = FormatReportBody(reportText);
        return reportText;
    }

    /*
     * 获取报文类型：TAF、METAR、SPECI
     * 如未找到报文类型，则抛出异IO常
     * */
    public static String getReportType(String reportMessage) {
        Assert.hasText(reportMessage, "读取的报文内容为空");
        String regex = "(METAR|TAF|SPECI)";
        Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
        Matcher matcher = pattern.matcher(reportMessage);
        if (matcher.find()) {
            for (int i = 0; i < matcher.groupCount(); i++) {
                if (!StringUtils.isEmpty(matcher.group(i))) {
                    return matcher.group(i);
                }
            }
        }
        return "";
    }

    /*
     * 获取机场四字代码
     * */
    public static String getReportAirport(String reportMessage) {
        /*String regex = "(\\s*[A-Z]{4}\\s)";
        Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
        Matcher matcher = pattern.matcher(reportMessage);
        if (matcher.find()) {
            for (int i = 0; i < matcher.groupCount(); i++) {
                if (!StringUtils.isEmpty(matcher.group(i))) {
                    String airportCode = matcher.group(i);
                    return airportCode.trim();
                }
            }
        }
        return "";*/
        // 正则表达式匹配四个连续的大写字母，不包含前后空格
        String regex = "\\b[A-Z]{4}\\b";

        Pattern pattern = Pattern.compile(regex);

        // 用于匹配reportMessage
        Matcher matcher = pattern.matcher(reportMessage);
        while (matcher.find()) {
            // 打印匹配的机场代码
            String airportCode = matcher.group();
            return airportCode.trim();
        }
        return "";
    }

    /**
     * @param fileName      文件全路径
     * @param reportMessage 报文数据内容
     *                      获取观测时间
     */
    public static Timestamp getReportTimeUTC(String fileName, String reportMessage) throws IOException, ParseException {
        String regexyyMM = "(\\d{8})";
        Pattern patternyyMM = Pattern.compile(regexyyMM, Pattern.MULTILINE);
        Matcher matcheryyMM = patternyyMM.matcher(fileName);
        boolean yyMMIsMatch = matcheryyMM.find();

        String regexMonth = "(\\d{8})";
        Pattern patternMonth = Pattern.compile(regexMonth);
        Matcher matcherMonth = patternMonth.matcher(fileName);
        boolean monthMatch = matcherMonth.find();

        String regexDDHHss = "(\\s+\\d{6}Z\\s+)";
        Pattern patternDDHHss = Pattern.compile(regexDDHHss);
        Matcher matcherDDHHss = patternDDHHss.matcher(reportMessage);
        boolean DDHHssMatch = matcherDDHHss.find();

        if (yyMMIsMatch && DDHHssMatch) {
            if (!StringUtils.isEmpty(matcheryyMM.group(0)) && !StringUtils.isEmpty(matcherDDHHss.group(0))) {
                String yyMMString = matcheryyMM.group(0).trim();
                String DDHHmmString = matcherDDHHss.group(0).trim();
                String monthString = matcherMonth.group(0).trim();
                //20230714 141330Z
                String year = yyMMString.substring(0, 4);
                String month = monthString.substring(4, 6);
                String dayInYyStr = yyMMString.substring(6, 8);
                String day = DDHHmmString.substring(0, 2);
                String hh = DDHHmmString.substring(2, 4);
                String mm = DDHHmmString.substring(4, 6);

                int dayInt = Integer.parseInt(day, 10);
                int dayInYyStrInt = Integer.parseInt(dayInYyStr, 10);
                int mmInt = Integer.parseInt(month);
                int yearInt = Integer.parseInt(year);
                //因数据存储延迟，上月数据存入次月中时，需要将月份减一
                if (dayInt > dayInYyStrInt) {
                    mmInt -= 1;
                    if (mmInt <= 0) {
                        mmInt = 12;
                        yearInt -= 1;
                    }
                }
                String reportDateSql = yearInt + "-" + mmInt + "-" + day + " " + hh + ":" + mm + ":" + "00";//2022-06-22 08:30:00
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                java.util.Date date = simpleDateFormat.parse(reportDateSql);

                return new Timestamp(date.getTime());
            }
        }
        throw new IOException("获取发报时间失败");
    }

    public static Timestamp getReportTimeUTCFoUpdate(String fileName, String reportMessage) throws IOException, ParseException {
        String regexyy = "(\\d{8})";
        Pattern patternyy = Pattern.compile(regexyy, Pattern.MULTILINE);
        Matcher matcheryy = patternyy.matcher(fileName);
        boolean yyIsMatch = matcheryy.find();

        String regexHHss = "(\\s+\\d{6}Z\\s+)";
        Pattern patternHHss = Pattern.compile(regexHHss);
        Matcher matcherHHss = patternHHss.matcher(reportMessage);
        boolean HHssMatch = matcherHHss.find();

        int HHssgrountCount = matcherHHss.groupCount();

        if (yyIsMatch == HHssMatch && HHssgrountCount > 0) {
            if (!StringUtils.isEmpty(matcheryy.group(0))) {
                String yyString = matcheryy.group(0).trim();
                String HHmmString = matcherHHss.group(0).trim();
                //20220101
                String year = yyString.substring(0, 4);
                //String year = "2022";
                //String month = yyString.substring(4,6);
                String month = yyString.substring(4, 6);
                String day = HHmmString.substring(0, 2);
                String hh = HHmmString.substring(2, 4);
                String mm = HHmmString.substring(4, 6);
                String reportDateSql = year + "-" + month + "-" + day + " " + hh + ":" + mm + ":" + "00";//2022-06-22 08:30:00

                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                java.util.Date date = simpleDateFormat.parse(reportDateSql);
                Timestamp timestamp = new Timestamp(date.getTime());  //date.getTime()获取时间戳
                return timestamp;
            }
        }
        throw new IOException("获取发报时间失败");
    }

    /**
     * @param timeUTC utc时间
     *                将UTC时间转换为北京时
     */
    public static Timestamp convertUTCtimeToLocal(Timestamp timeUTC) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(timeUTC);
        calendar.add(Calendar.HOUR, 8);
        Timestamp timestamp = new Timestamp(calendar.getTime().getTime());
        return timestamp;
    }

    /**
     * 获取温度
     */
    public static int getTfromMessage(String reportMessage) {
        //String regex = "([M]?\\d{2}/[M]?\\d{2})";
        String regex = "^(\\d{2,3}\\/\\d{2,3})$";
        Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
        Matcher matcher = pattern.matcher(reportMessage);
        List<String> matchers = new ArrayList<>();
        while (matcher.find()) {
            for (int i = 1; i <= matcher.groupCount(); i++) {
                matchers.add(matcher.group(i));
            }
        }
        int temp = -999;
        try {
            String tempStr = matchers.get(matchers.size() - 1).split("/")[0].trim();
            if (tempStr.contains("M")) {
                tempStr = tempStr.replace("M", "-");
            }
            temp = Integer.parseInt(tempStr);
        } catch (Exception e) {
            return temp;
        }
        return temp;
    }

    /**
     * @param reportMessage 报文正文
     * @return 返回报文中天气现象
     */
    public static String getWeatherPhenomenonFromMessage(String reportMessage) throws IOException {
        String type = getReportType(reportMessage);
        String reportType = "AMD";
        if (type.length() >= 5) {
            reportType = getReportType(reportMessage).substring(0, 4);
        }
        String airportCode = getReportAirport(reportMessage);
        String regex = "([-]?[+]?[A-Z]{2,6})";
        Pattern pattern;
        pattern = Pattern.compile(regex, Pattern.MULTILINE);
        Matcher matcher = pattern.matcher(reportMessage);
        String weatherPhenomenon = "";
        while (matcher.find()) {
            int groupCount = matcher.groupCount();
            for (int i = 0; i < groupCount; i++) {
                String t = matcher.group(i);
                if (!StringUtils.isEmpty(t)) {
                    if (!t.equals(reportType) && !t.equals(airportCode)
                            && !t.equals("MPS") && !t.equals("FEW")
                            && !t.equals("COR") && !t.equals("FEW")
                            && !t.equals("RETS") && !t.equals("NSC")
                            && !t.equals("BECMG") && !t.equals("TL")
                            && !t.equals("AUTO") && !t.equals("NSW")
                            && !t.equals("AT") && !t.equals("FM")
                            && !t.equals("SCT") && !t.equals("BKN")
                            && !t.equals("OVC") && !t.equals("NOSIG")
                            && !t.equals("TEMO") && !t.equals("CNL")
                            && !t.equals("NCD") && !t.equals("VV")
                            && !t.equals("TCU") && !t.equals("CB")
                            && !t.equals("SKC") && !t.equals("TEMPO")
                            && !t.equals("KT") && !t.equals(type)
                            && !t.contains("RE")
                            && !t.equals("TX") && !t.equals("TXM") && !t.equals("TN") && !t.equals("TNM")
                            && !t.equals("VRB") && !t.equals("CAVOK")) {
                        weatherPhenomenon = weatherPhenomenon + " " + matcher.group(i);
                    }
                }
            }
        }
        return weatherPhenomenon.trim();
    }

    /**
     * @param reportMessage 报文正文
     * @return 返回露点气温
     */
    public static int getDpfromMessage(String reportMessage) throws IOException {
        //String regex = "([M]?\\d+/[M]?\\d+)";
        String regex = "^(\\d{2,3}\\/\\d{2,3})$";
        Pattern pattern;
        pattern = Pattern.compile(regex, Pattern.MULTILINE);
        Matcher matcher = pattern.matcher(reportMessage);
        List<String> matchers = new ArrayList<>();
        while (matcher.find()) {
            for (int i = 1; i <= matcher.groupCount(); i++) {
                matchers.add(matcher.group(i));
            }
        }
        int dp = -999;
        try {
            String dpStr = matchers.get(matchers.size() - 1).split("/")[1].trim();
            if (dpStr.contains("M")) {
                dpStr = dpStr.replace("M", "-");
            }
            dp = Integer.parseInt(dpStr);
        } catch (Exception e) {
            return dp;
        }
        return dp;
    }

    /*
     * 风向风速组
     * */
    public static String getWdAndWsFromReportMessage(String reportMessage) {
        String regex = "([V]?[R]?[B]?\\d+[G]?\\d+(MPS|KT))";
        Pattern pattern;
        pattern = Pattern.compile(regex, Pattern.MULTILINE);
        Matcher matcher = pattern.matcher(reportMessage);
        if (matcher.find()) {
            for (int i = 0; i < matcher.groupCount(); i++) {
                if (!StringUtils.isEmpty(matcher.group(i))) {
                    String wdStr = matcher.group(i).trim();//15010KT
                    return wdStr;
                }
            }
        }
        return "NoWd";
    }

    /*
     * 将报文数据中\r\n字符替换为空格
     * */
    public static String FormatReportBody(String reportBody) {
        reportBody = reportBody.replaceAll("[\\t\\n\\r]", " ");//将内容区域的回车换行去除
        return reportBody;
    }

    /**
     * @param reportMessage 报文正文
     * @return 风速组，如果有VRB则返回-1
     */
    public static int getWdFromReportMessage(String reportMessage) throws IOException {
        String wdAndWsStr = getWdAndWsFromReportMessage(reportMessage);
        String wdStr = wdAndWsStr.substring(0, 3);
        try {
            return Integer.parseInt(wdStr);
        } catch (Exception e) {
            return -999;
        }
    }

    /**
     * @param reportMessage 报文正文
     * @return 风速单位，返回KT或者MPS
     */
    public static String getWdTypeFromReportMessage(String reportMessage) throws IOException {
        String wdAndWsStr = getWdAndWsFromReportMessage(reportMessage);
        int strLength = wdAndWsStr.length();
        int strStart = strLength;
        if (wdAndWsStr.contains("MPS")) {
            strStart -= 3;
        }
        if (wdAndWsStr.contains("KT")) {
            strStart -= 2;
        }
        String wdTypeStr = wdAndWsStr.substring(strStart, strLength);
        return wdTypeStr;
    }

    /**
     * @param reportMessage 报文正文
     * @return 风速
     */
    public static int getWsFromReportMessage(String reportMessage) throws IOException {
        String wdAndWsStr = getWdAndWsFromReportMessage(reportMessage);
        int wsInt = -999;
        try {
            if ("NoWd" != wdAndWsStr) {
                String wsStr = wdAndWsStr.substring(3, 5);
                wsInt = Integer.parseInt(wsStr);
            }
        } catch (Exception exception) {
            exception.printStackTrace();
            throw exception;
        }
        return wsInt;
    }

    /**
     * @param reportMessage 报文体
     * @return 能见度
     */
    public static int getVisFromReportMessage(String reportMessage) throws IOException {
        String regex = "(CAVOK|\\s\\d{4}\\s)";
        Pattern pattern;
        pattern = Pattern.compile(regex, Pattern.MULTILINE);
        Matcher matcher = pattern.matcher(reportMessage);
        if (matcher.find()) {
            for (int i = 0; i < matcher.groupCount(); i++) {
                if (!StringUtils.isEmpty(matcher.group(i))) {
                    String visStr = matcher.group(i).trim();
                    if (visStr.equals("CAVOK")) {
                        return 9999;
                    } else {
                        return Integer.parseInt(visStr);
                    }
                }
            }
        }
        return -999;
    }

    /**
     * @param
     * @return 获取云组
     */
    public static String getCloudFromReportMessage(String reportMessage) {
        String regex = "(VV\\d{3}|[A-Z]{3}\\d{3}[A-Z]{2,3}|NSC|NCD|SKC|[A-Z]{3}\\d{3})";
        Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
        Matcher matcher = pattern.matcher(reportMessage);
        StringBuilder stringBuilder = new StringBuilder();
        while (matcher.find()) {
            for (int i = 0; i < matcher.groupCount(); i++) {
                if (!StringUtils.isEmpty(matcher.group(i))) {
                    stringBuilder.append(matcher.group(i).trim()).append(" ");
                }
            }
        }
        return stringBuilder.toString();
    }

    /**
     * @param reportMessage 报文体
     * @param cloudHighSeq  第几组云高，值为0-2
     */
    public static int getReportCldH(String reportMessage, CloudHighSeq cloudHighSeq) {
        String cldStr = getCloudFromReportMessage(reportMessage);
        if (cldStr.trim().equals("NSC")) {
            return 9999;
        }
        String[] strings = cldStr.split(" ");
        int cldsCount = strings.length;
        int cloudH = 9999;
        if (cldsCount != 0) {
            if (cloudHighSeq.ordinal() < strings.length) {
                String regex = "\\d{3}";
                Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
                Matcher matcher = pattern.matcher(strings[cloudHighSeq.ordinal()]);
                if (matcher.find()) {
                    cloudH = Integer.parseInt(matcher.group(0).trim());
                    cloudH = cloudH * 30;
                }
            }
        }
        return cloudH;
    }

    /**
     * @param reportMessage 报文体
     * @param cloudHighSeq  第几组云量，值为0-2
     */
    public static Integer getReportCldM(String reportMessage, CloudHighSeq cloudHighSeq) {
        String cldStr = getCloudFromReportMessage(reportMessage);
        int cldM = 0;
        if (cldStr.trim().equals("")) {
            return cldM;
        }
        String[] strings = cldStr.split(" ");
        int cldsCount = strings.length;
        String cloudM = " ";
        if (cldsCount != 0) {
            if (cloudHighSeq.ordinal() < strings.length) {
                String regex = "([A-Z]{3})";
                Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
                Matcher matcher = pattern.matcher(strings[cloudHighSeq.ordinal()]);

                if (matcher.find()) {
                    cloudM = matcher.group(0).trim().substring(0, 3);
                    switch (cloudM) {
                        case "FEW":
                            cldM = 2;
                            break;
                        case "SCT":
                            cldM = 4;
                            break;
                        case "BKN":
                            cldM = 7;
                            break;
                        case "OVC":
                            cldM = 8;
                            break;
                        default:
                            cldM = 0;
                            break;
                    }
                }
            }
        }
        return cldM;
    }

    /**
     * 获取报文中修正海压
     *
     * @param reportMessage 报文正文
     */
    public static int getQfromMessage(String reportMessage) {
        String regex = "Q\\d{4}";
        Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
        Matcher matcher = pattern.matcher(reportMessage);
        String qStr = "";
        int q = -999;
        if (matcher.find()) {
            qStr = matcher.group(0).trim();
            q = Integer.parseInt(qStr.replace("Q", "").trim());
        }
        return q;
    }

    public static String intToStr(int i) {
        return String.valueOf(i);
    }

    /*
     * 报文翻译
     * */
    @Deprecated
    public static String translate(String fileName, String reportMessage, String airportName) throws IOException, ParseException {
        Timestamp reportTimeUTC = getReportTimeUTC(fileName, reportMessage);
        Timestamp utCtimeToLocal = convertUTCtimeToLocal(reportTimeUTC);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        String timeStr = simpleDateFormat.format(utCtimeToLocal.getTime());
        String[] timeStrings = timeStr.split(" ");
        int wd = getWdFromReportMessage(reportMessage);
        String wdStr = intToStr(wd);
        int ws = getWsFromReportMessage(reportMessage);
        String wsStr = intToStr(ws);
        int t = getTfromMessage(reportMessage);
        String tStr = intToStr(t);
        int q = getQfromMessage(reportMessage);
        String qStr = intToStr(q);
        String stringBuilder = "当前机场：" + airportName + "\n" +
                "日期：" + timeStrings[0] + "\n" +
                "时间：" + timeStrings[1] + "\n" +
                "风向风速：" + wdStr + "° " + wsStr + "m/s" + "\n" +
                "温度：" + tStr + "℃" + "\n" +
                "修正海压：" + qStr + "hPa" + "\n";
        return stringBuilder;
    }

    public static String translateForUpdate(String fileName, String reportMessage, String airportName) throws IOException, ParseException {
        Timestamp reportTimeUTC = getReportTimeUTCFoUpdate(fileName, reportMessage);
        Timestamp utCtimeToLocal = convertUTCtimeToLocal(reportTimeUTC);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        String timeStr = simpleDateFormat.format(utCtimeToLocal.getTime());
        String[] timeStrings = timeStr.split(" ");
        int wd = getWdFromReportMessage(reportMessage);
        String wdStr = intToStr(wd);
        int ws = getWsFromReportMessage(reportMessage);
        String wsStr = intToStr(ws);
        int t = getTfromMessage(reportMessage);
        String tStr = intToStr(t);
        int q = getQfromMessage(reportMessage);
        String qStr = intToStr(q);
        String stringBuilder = "当前机场：" + airportName + "\n" +
                "日期：" + timeStrings[0] + "\n" +
                "时间：" + timeStrings[1] + "\n" +
                "风向风速：" + wdStr + "° " + wsStr + "m/s" + "\n" +
                "温度：" + tStr + "℃" + "\n" +
                "修正海压：" + qStr + "hPa" + "\n";
        return stringBuilder;
    }

    public static enum CloudHighSeq {
        first, second, third
    }
}
